package com.zjw.zy.setting

import com.zjw.zy.smi.JustWithIt
import com.zjw.zy.utils.GsonUtils
import com.zjw.zy.utils.LogUtils
import com.zjw.zy.utils.SharePrefUtils
import java.lang.Exception
import java.util.ArrayList

/**
 * @author ：zhong.jw
 * @date ：Created in 2022/10/20 11:38
 *
 * 设备存储，无云端控制
 */
object SettingStorage {

    private const val TAG = "SettingStorage"

    private val mObservers: MutableMap<Class<out AbsOption<*>>, MutableList<JustWithIt<AbsOption<*>>>> =
        HashMap()

    fun addOptionObserver(option: Class<out AbsOption<*>>, call: JustWithIt<AbsOption<*>>) {
        LogUtils.d(TAG, "addOptionObserver $option $call")
        val list = mObservers.computeIfAbsent(option) { ArrayList() }
        list.add(call)
    }

    fun removeOptionObserver(option: Class<out AbsOption<*>>, call: JustWithIt<AbsOption<*>>) {
        LogUtils.d(TAG, "removeOptionObserver $option $call")
        val list = mObservers[option]
        list?.remove(call)
    }

    fun setOption(option: AbsOption<*>) {
        LogUtils.d(TAG, "setOption $option")
        val key = option.requireOptionKey()
        val value = GsonUtils.toJson(option)
        SharePrefUtils.putString(key, value)
        considerNotify(option)
    }

    private fun considerNotify(option: AbsOption<*>) {
        LogUtils.d(TAG, "considerNotify $option")
        val listeners: List<JustWithIt<AbsOption<*>>>? = mObservers[option::class.java]
        if (listeners != null) {
            for (call in listeners) {
                call.onWith(option)
            }
        }
    }

    fun <T : AbsOption<*>?> getOption(option: Class<T>): T? {
        val key = option.name
        val contain = SharePrefUtils.contain(key)
        if (!contain) {
            return null
        }
        val json = SharePrefUtils.getString(key, "")
        var obj: T? = null
        try {
            obj = GsonUtils.fromJson(json, option)
        } catch (e: Exception) {
            LogUtils.e(TAG, e.message)
        }
        LogUtils.d(TAG, "getOption $option==>$obj")
        return obj
    }

    fun resetOption() {
        setOption(LocationShareOption().apply { this.value = true })
    }
}